using M13.Base;
using M13.GameSystem;
using M13.Utility;
using QFramework;
using System;
using System.Buffers;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
using Debug = UnityEngine.Debug;

namespace M13.Game.World
{
    public class WorldBuilder : MonoBehaviour, IController, ICanSendEvent//��֣�7
    {
        private List<RegionBulider> _regionBuliders = new List<RegionBulider>();

        [FormerlySerializedAs("_buildConfig")]
        [Header("创建世界配置")]
        [SerializeField] private WorldBuildConfig buildConfig;

        [FormerlySerializedAs("_saveConfig")] [SerializeField] private SaveConfig saveConfig;



        [FormerlySerializedAs("_AllowToGenerateWorld")]
        [Space(10)]

        [SerializeField] bool allowToGenerateWorld = false;

        [FormerlySerializedAs("_regionIndex")] [SerializeField] int regionIndex = 0;

        [FormerlySerializedAs("_taskNum")] [SerializeField] int taskNum;

        private ISaveSystem _saveSystem;

        private byte[] _regionDataBuffer;

        private void Start()
        {
            this.RegisterEvent<CreateWorld>(e => OnInit(e.saveConfig));
            _saveSystem = this.GetSystem<ISaveSystem>();
            //regionDataBuffer = ArrayPool<byte>.Shared.Rent(811008);
        }

        public void OnInit(SaveConfig saveConfig)
        {
            _regionBuliders.Clear();
            this.saveConfig = saveConfig;
            allowToGenerateWorld = true;
            regionIndex = 0;
            RegionsCoord();
        }

        private void RegionsCoord()
        {
            for (int x = -(buildConfig.worldRegionSizeNum - 1) / 2; x <= (buildConfig.worldRegionSizeNum - 1) / 2; x++) 
            {
                for (int y = -(buildConfig.worldRegionSizeNum - 1) / 2; y <= (buildConfig.worldRegionSizeNum - 1) / 2; y++) 
                {
                    RegionBulider regionBulider = new RegionBulider(new Vector2Int(x, y), saveConfig, buildConfig);
                    _regionBuliders.Add(regionBulider);
                }
            }
        }

        int _totalTime = 0;
        private void Update()
        {
            
            taskNum = _regionBuliders.Count;
            //û��Ҫ�������������ݣ����������Ѿ����������
            if (_regionBuliders.Count == 0 || regionIndex > _regionBuliders.Count - 1)
            {

                //_stopwatch.Stop();
                //Debug.Log(_stopwatch.ElapsedMilliseconds);
                allowToGenerateWorld = false;
                
                return;
            }
            

            //��ʼ�������򣬲���������������δȫ���������
            if (allowToGenerateWorld && !_regionBuliders[regionIndex].ChunksOfRegionGenerateFinished())
            { 
                _regionBuliders[regionIndex].GenerateChunkData();
            }
            
            //�����������鴴������ˣ���ʼ������һ������
            if (_regionBuliders[regionIndex].ChunksOfRegionGenerateFinished())
            {
                #region �ڴ˴���ȡregion��������������������

                byte[] regionData = _regionBuliders[regionIndex].GetRegionDataOnFinished();
                byte[] regionBoot = _regionBuliders[regionIndex].GetRegionBootOnFinished();

                _regionDataBuffer = ArrayPool<byte>.Shared.Rent(regionData.Length + regionBoot.Length);
                Buffer.BlockCopy(regionBoot, 0, _regionDataBuffer, 0, regionBoot.Length);
                Buffer.BlockCopy(regionData, 0, _regionDataBuffer, regionBoot.Length, regionData.Length);

                byte[] regionSecondaryCompressedData = Clzf2.Compress(_regionDataBuffer);
                _saveSystem.CreateRegionFile(saveConfig.name, _regionBuliders[regionIndex].RegionLocalCoord, regionSecondaryCompressedData);

                #endregion

                regionIndex++;

                if (regionIndex == taskNum)
                {
                    Debug.Log("ȫ�����򴴽����");
                    CreateWorldFinished createWorldFinished;
                    createWorldFinished.saveConfig = saveConfig;
                    this.SendEvent<CreateWorldFinished>(createWorldFinished);
                }
            }
        }


        public IArchitecture GetArchitecture()
        {
            return GameArchitecture.Interface;
        }
    }
}